package com.ndp.fb.walle.business.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.enums.publish.PublishResultType;
import com.ndp.fb.enums.publish.PublishStatus;
import com.ndp.fb.exception.BusinessException;
import com.ndp.fb.model.DateModel;
import com.ndp.fb.mq.api.service.schedulerservice.AdPublishSchedulerService;
import com.ndp.fb.rdb.api.PublishBatchRdbService;
import com.ndp.fb.rdb.api.PublishResultDetailRdbService;
import com.ndp.fb.rdb.api.PublishResultRdbService;
import com.ndp.fb.rdb.model.*;
import com.ndp.fb.util.DateFormatUtil;
import com.ndp.fb.util.ListUtil;
import com.ndp.fb.walle.business.PublishBatchService;
import com.ndp.fb.walle.model.bo.publishbatch.result.PublishBatchDetailBo;
import com.ndp.fb.walle.model.vo.publishbatch.result.PublishBatchDetailInfoResult;
import com.ndp.fb.walle.model.vo.publishbatch.result.PublishResultFailDetail;
import com.ndp.fb.walle.model.vo.publishbatch.result.PulishBatchEachAccountInfo;
import com.ndp.fb.walle.util.ResponseUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by infi on 2015/1/29.
 */
@Component
public class PublishBatchServiceImpl implements PublishBatchService {
    private final org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());

    @Reference
    private PublishBatchRdbService publishBatchRdbService;

    @Reference
    private PublishResultDetailRdbService publishResultDetailRdbService;

    @Reference
    private PublishResultRdbService publishResultRdbService;

    @Reference
    private AdPublishSchedulerService adPublishSchedulerService;

    @Override
    public Pager<PublishBatchDetailBo> findAllPublishBatchByUserId(String userId, Integer start, Integer noSize) throws BusinessException {
        String format = "yyyy-MM-dd HH:mm:ss";
        Pager<PublishBatchDetailBo> pagerBos = new Pager<>();
        List<PublishBatchDetailBo> bos = new ArrayList<>();
        // 1、获取批次信息
        Pager<PublishBatch> publishBatches = publishBatchRdbService.findPagerByUserIdOrderByCreateTime(userId, start, noSize);

        // 2、获取批次结果信息  publish_result
        PublishBatchDetailBo bo;
        for (PublishBatch batch : publishBatches.getResultList())
        {
            bo = new PublishBatchDetailBo();
            //add by giser 2014.12.24
            bo.setAllAdGroupCount(batch.getAllAdGroupCount());
            bo.setAllAdSetCount(batch.getAllAdSetCount());
            bo.setAllCampaignCount(batch.getAllCampaignCount());
            bo.setAllCreativeCount(batch.getAllAdCreativeCount());
            bo.setAllPublishAccountCount(batch.getAllAdAccountCount());
            bo.setPublishStatus(batch.getPublishStatus());
            bo.setId(batch.getId());
            bo.setBidInfo(batch.getBidInfo());
            bo.setConfiguration(batch.getConfiguration());
            DateModel createTimeDateModel = DateFormatUtil.getDate(batch.getCreateTime(), format, batch.getTimezone(),DateFormatUtil.TIME_ZONE_UTC);
            bo.setCreateTime(createTimeDateModel.getTimeString());
            bo.setDailyBudget(batch.getDailyBudget());
            bo.setLifetimeBudget(batch.getLifetimeBudget());
            if (batch.getEndTime() != null)
            {
                DateModel endDateModel = DateFormatUtil.getDate(batch.getEndTime(), format, batch.getTimezone(),DateFormatUtil.TIME_ZONE_UTC);
                bo.setEndTime(endDateModel.getTimeString());
                bo.setEndUtcTime(endDateModel.getUtcTime());
            } else
            {
                bo.setEndTime("");
                bo.setEndUtcTime(0L);
            }
            DateModel startDateModel = DateFormatUtil.getDate(batch.getStartTime(), format, batch.getTimezone(),DateFormatUtil.TIME_ZONE_UTC);
            bo.setStartTime(startDateModel.getTimeString());
            bo.setStartUtcTime(startDateModel.getUtcTime());
            bo.setObjectName(batch.getConnectionObjectName());
            bo.setPublishBatchName(batch.getPublishBatchName());
            bo.setRetryCnt(batch.getRetryCnt());   //Add by evan 2015-07-12 重试需求
            bo.setTimezone(batch.getTimezone());

            //组装返回的业务数据  特别是发布账户数、营销活动数、广告系列数、广告数
            //Modify by EVAN 2015-01-24
            List<CountDetailByBatchIdAndTypesBean> tempCount1 = publishBatchRdbService.countDetailByBatchIdAndTypes(batch.getId(), PublishResultType.adGroupSuccess.getIndex()+ CommonConstants.SYMBOL_COMMA+PublishResultType.campaignGroupSuccess.getIndex()+CommonConstants.SYMBOL_COMMA+PublishResultType.adSetSuccess.getIndex()+CommonConstants.SYMBOL_COMMA+ PublishResultType.adCreativeSuccess.getIndex());
            setCount(bo, tempCount1);

            //set campaginname adsetname adname
            PublishBatchCSAName csaNameByBatch = publishBatchRdbService.findCSANameByBatchId(batch.getId());
            if(csaNameByBatch!=null){
                bo.setCampaignName(csaNameByBatch.getCampaignName());
                bo.setAdSetName(csaNameByBatch.getAdsetName());
                bo.setAdName(csaNameByBatch.getAdgroupName());
            }
            bos.add(bo);
         }
        pagerBos.setResultList(bos);
        pagerBos.setTotalSize(publishBatches.getTotalSize());
        return pagerBos;
    }



    @Override
    public List<PublishBatch> searchPublishBatchByNameAndUserId(String batchName, String userId) throws BusinessException {
        return publishBatchRdbService.searchPublishBatchByNameAndUserId(batchName, userId);
    }


    @Override
    public List<PublishBatchDetailBo> findPublishBatchByIdsAndUserId(String userId, Long[] ids) throws BusinessException {
        String format = "yyyy-MM-dd HH:mm:ss";
        List<PublishBatchDetailBo> bos = new ArrayList<>();
        // 1、获取批次信息
        List<PublishBatch> publishBatches = publishBatchRdbService.findByIdsAndUserId(ids, userId);
        // 2、获取批次结果信息  publish_result
        for (PublishBatch batch : publishBatches)
        {
            PublishBatchDetailBo bo = new PublishBatchDetailBo();
            //发布批次中增加发布广告账号，发布campaign，发布adset，发布adgrop等的总数
            //add by giser 2014.12.24
            bo.setAllAdGroupCount(batch.getAllAdGroupCount());
            bo.setAllAdSetCount(batch.getAllAdSetCount());
            bo.setAllCampaignCount(batch.getAllCampaignCount());
            bo.setAllCreativeCount(batch.getAllAdCreativeCount());
            bo.setAllPublishAccountCount(batch.getAllAdAccountCount());
            bo.setPublishStatus(batch.getPublishStatus());

            bo.setId(batch.getId());
            bo.setBidInfo(batch.getBidInfo());
            bo.setConfiguration(batch.getConfiguration());
            DateModel createTimeDateModel = DateFormatUtil.getDateModel(batch.getCreateTime(), format, batch.getTimezone());
            bo.setCreateTime(createTimeDateModel.getTimeString());
            bo.setDailyBudget(batch.getDailyBudget());
            bo.setLifetimeBudget(batch.getLifetimeBudget());
            if (batch.getEndTime() != null)
            {
                DateModel endDateModel = DateFormatUtil.getDateModel(batch.getEndTime(), format, batch.getTimezone());
                bo.setEndTime(endDateModel.getTimeString());
                bo.setEndUtcTime(endDateModel.getUtcTime());
            } else
            {
                bo.setEndTime("");
                bo.setEndUtcTime(0L);
            }
            DateModel startDateModel = DateFormatUtil.getDateModel(batch.getStartTime(), format, batch.getTimezone());
            bo.setStartTime(startDateModel.getTimeString());
            bo.setStartUtcTime(startDateModel.getUtcTime());
            bo.setObjectName(batch.getConnectionObjectName());
            bo.setProductConfId(batch.getProductConfId());
            bo.setPublishBatchName(batch.getPublishBatchName());
            bo.setRetryCnt(batch.getRetryCnt());   //Add by evan 2015-07-12 重试需求
            bo.setTimezone(batch.getTimezone());
            //组装返回的业务数据  特别是发布账户数、营销活动数、广告系列数、广告数
            //Modify by EVAN 2015-01-24
            List<CountDetailByBatchIdAndTypesBean> tempCount1 = publishBatchRdbService.countDetailByBatchIdAndTypes(batch.getId(), PublishResultType.adGroupSuccess.getIndex()+CommonConstants.SYMBOL_COMMA+PublishResultType.campaignGroupSuccess.getIndex()+CommonConstants.SYMBOL_COMMA+PublishResultType.adSetSuccess.getIndex()+CommonConstants.SYMBOL_COMMA+PublishResultType.adCreativeSuccess.getIndex());
            setCount(bo, tempCount1);
            bos.add(bo);
        }
        return bos;
    }

    private void setCount(PublishBatchDetailBo bo, List<CountDetailByBatchIdAndTypesBean> tempCount1) {
        if(ListUtil.isNotEmpty(tempCount1))
        {
            for(CountDetailByBatchIdAndTypesBean bean : tempCount1)
            {
                if(bean.getType().equals(PublishResultType.adGroupSuccess.getIndex()))
                {
                    bo.setAdGroupCount(bean.getCount());
                }
                else if(bean.getType().equals(PublishResultType.campaignGroupSuccess.getIndex()))
                {
                    bo.setCampaignCount(bean.getCount());
                }
                else if(bean.getType().equals(PublishResultType.adSetSuccess.getIndex()))
                {
                    bo.setAdSetCount(bean.getCount());
                }
                else if(bean.getType().equals(PublishResultType.adCreativeSuccess.getIndex()))
                {
                    bo.setCreativeCount(bean.getCount());
                }else
                {
                    logger.info("回来的类型不在查找输入内。");
                }
            }
        }
    }


    @Override
    public PublishBatchDetailInfoResult searchPublishBatchDetailInfoById(Long id) {

        PublishBatchDetailInfoResult result = new PublishBatchDetailInfoResult();
        //1、获得带账号的批次信息
        List<PublishBatchResult> batchResults = publishResultRdbService.searchPublishResultInfo(id);
        if(ListUtil.isNotEmpty(batchResults))
        {
            result.setPublishBatchName(batchResults.get(0).getPublishBatchName());
            result.setPublishStatus(batchResults.get(0).getPublishStatus());
            List<PulishBatchEachAccountInfo> eachAccountInfos = new ArrayList<>();
            PulishBatchEachAccountInfo eachAccountInfo;
            for(PublishBatchResult batchResult : batchResults)
            {
                eachAccountInfo = new PulishBatchEachAccountInfo();
                eachAccountInfo.setFbAccountId(batchResult.getAccountId());
                if(batchResult.getAccountName() == null || "".equals(batchResult.getAccountName().trim()))
                {
                    eachAccountInfo.setAccountName(batchResult.getAccountId());
                }
                else
                {
                    eachAccountInfo.setAccountName(batchResult.getAccountName());
                }
                eachAccountInfo.setAdCreativeCountAll(batchResult.getAdcreativeCount());
                eachAccountInfo.setCompaignGroupAll(batchResult.getAdcampaignCount());
                eachAccountInfo.setAdSetCountAll(batchResult.getAdsetCount());
                eachAccountInfo.setAdGroupCountAll(batchResult.getAdgroupCount());

                //根据publish_result_id查询 多少个成功
                eachAccountInfo.setAdCreativeCount(publishResultDetailRdbService.countDetailByPublishResultIdAndTypes(batchResult.getPublishResultId(),PublishResultType.adCreativeSuccess.getIndex() + ""));
                eachAccountInfo.setCompaignGroupCount(publishResultDetailRdbService.countDetailByPublishResultIdAndTypes(batchResult.getPublishResultId(), PublishResultType.campaignGroupSuccess.getIndex() + ""));
                eachAccountInfo.setAdSetCount(publishResultDetailRdbService.countDetailByPublishResultIdAndTypes(batchResult.getPublishResultId(), PublishResultType.adSetSuccess.getIndex() + ""));
                eachAccountInfo.setAdGroupCount(publishResultDetailRdbService.countDetailByPublishResultIdAndTypes(batchResult.getPublishResultId(), PublishResultType.adGroupSuccess.getIndex() + ""));

                //set错误记录
                final String types = PublishResultType.adCreativeFail.getIndex() + CommonConstants.SYMBOL_COMMA
                        + PublishResultType.campaignGroupFail.getIndex() + CommonConstants.SYMBOL_COMMA
                        + PublishResultType.adSetFail.getIndex() + CommonConstants.SYMBOL_COMMA
                        + PublishResultType.adGroupFail.getIndex()+ CommonConstants.SYMBOL_COMMA
                        + PublishResultType.preProcessPublishFail.getIndex();
                List<PublishResultDetail> details = publishResultDetailRdbService.searchDetailByPublishResultIdAndTypes(batchResult.getPublishResultId(), types);
                if(ListUtil.isNotEmpty(details))
                {
                    eachAccountInfo.setFailCount(details.size());
                    List<PublishResultFailDetail> failDetails = new ArrayList<>();
                    for(PublishResultDetail detail : details)
                    {
                        PublishResultFailDetail failDetail = new PublishResultFailDetail();
                        failDetail.setResult(detail.getResult());
                        failDetail.setObjectType(detail.getObjectType());
                        failDetail.setParam(detail.getParam());
                        failDetails.add(failDetail);
                        String exceptionMsg=detail.getException();
                        //如果是error code,获取国际化的msg，如果不是，set 原始的 exception msg
                        if(NumberUtils.isNumber(exceptionMsg)){
                            failDetail.setException(ResponseUtils.getMsgByErrorCode(exceptionMsg));
                        }else{
                            failDetail.setException(detail.getException());
                        }

                    }
                    eachAccountInfo.setPublishResultFailDetails(failDetails);
                }
                else
                {
                    eachAccountInfo.setFailCount(0);
                }

                eachAccountInfos.add(eachAccountInfo);
            }
            result.setPulishBatchEachAccountInfos(eachAccountInfos);

        }

        return result;
    }

    @Override
    public void retry(Long batchId, String userId)
    {
        PublishBatch publishBatch = publishBatchRdbService.findById(batchId, userId);
        //确定是失败的批次 并且 重试次数不超过3次
        if(publishBatch != null && publishBatch.getPublishStatus() == PublishStatus.FAIL.getCode()&& publishBatch.getRetryCnt() < 3)
        {
            if(CommonConstants.PRE_FAIL.equals(publishBatch.getFailType())||publishBatch.getFailType()==null){
                publishBatchRdbService.updateStatsAndRetryCntAndTimeById(publishBatch.getId(), PublishStatus.WAIT_PRE_PROCESS.getCode());
            }else {
                logger.info("redo batch publish ,batchId:{}",batchId);
                // 1、更新批次正在重试 重试次数+1
                publishBatchRdbService.updateStatsAndRetryCntAndTimeById(publishBatch.getId(), PublishStatus.REDO.getCode());
            }

        }
    }

}
